//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#include "objenum.h"
#include "helper.h"
#include <aura.h>

#define LOCK_LIST   LOCK_START(m_hListLock)
#define UNLOCK_LIST LOCK_END(m_hListLock)

PInterface CObjectEnumerator::Probe(
    /* [in]  */ REIID riid)
{
    if (riid == EIID_IInterface) {
        return (IInterface *)(IObjectEnumerator *)this;
    }
    else if (riid == EIID_IObjectEnumerator) {
        return (IObjectEnumerator *)this;
    }
    else if (riid == EIID_CLASS_INFO) {
        return (PInterface)&ECLSID_CObjectEnumerator;
    }
    else if (riid == EIID_INTERFACE_INFO) {
        return (PInterface) &EIID_IObjectEnumerator;
    }
    return NULL;
}

UInt32 CObjectEnumerator::AddRef()
{
    Int32 nRef = m_cRef.Increment();
    return (UInt32)nRef;
}

UInt32 CObjectEnumerator::Release()
{
    Int32 nRef = m_cRef.Decrement();
    if (nRef == 0) {
        delete this;
    }
    return (UInt32)nRef;
}

ECode CObjectEnumerator::Aggregate(
    /* [in]  */ AggregateType type,
    /* [in]  */ PInterface pObject)
{
    return E_NOT_IMPLEMENTED;
}

ECode CObjectEnumerator::GetDomain(
    /* [out] */ PInterface * ppObject)
{
    return E_NOT_IMPLEMENTED;
}

ECode CObjectEnumerator::Current(
    /* [out] */ PInterface * ppObject)
{
    if (NULL == ppObject) {
        return E_INVALID_ARGUMENT;
    }

    LOCK_LIST;
    if ((NULL == m_pCurrentNode)
        || (m_pCurrentNode == m_pListHead)) {
        UNLOCK_LIST;
        return E_INVALID_OPERATION;
    }

    if (m_originalListState != *m_pListState) {
        m_pCurrentNode = NULL;
        UNLOCK_LIST;
        return E_INVALID_OPERATION;
    }

    *ppObject = (static_cast<ObjectEnumeratorNode *>(m_pCurrentNode))->GetObject();
    (*ppObject)->AddRef();
    UNLOCK_LIST;

    return NOERROR;
}

ECode CObjectEnumerator::MoveNext(
    /* [out] */ Boolean * pSucceeded)
{
    if (NULL == pSucceeded) {
        return E_INVALID_ARGUMENT;
    }

    *pSucceeded = FALSE;
    LOCK_LIST;
    if (NULL == m_pCurrentNode) {
        UNLOCK_LIST;
        return E_INVALID_OPERATION;
    }

    if (m_originalListState != *m_pListState) {
        m_pCurrentNode = NULL;
        UNLOCK_LIST;
        return E_INVALID_OPERATION;
    }
    if (m_pCurrentNode == m_pListHead->Prev()) {
        m_pCurrentNode = NULL;
        UNLOCK_LIST;
        return NOERROR;
    }

    m_pCurrentNode = m_pCurrentNode->Next();
    UNLOCK_LIST;

    *pSucceeded = TRUE;
    return NOERROR;
}

ECode CObjectEnumerator::Reset()
{
    LOCK_LIST;
    m_pCurrentNode = m_pListHead;
    m_originalListState = *m_pListState;
    UNLOCK_LIST;
    return NOERROR;
}

